#include "perseus.h"
#include "perseusdbg.h"
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>


/******************************************************/
/* Main test procedure for the libperseus             */
/* The file to protect is given as first argument to  */
/* the program (argv[1])                              */
/******************************************************/
int main(int argc, char * argv[]) 
 {
  struct stat st;
  PUNCT_CONC_CODE * Pcc;
  NOISE_GEN * NGen;
  INIT_NOISE_GEN * aKey;
  unsigned long int i, data_size, dataLength;
  unsigned long int encoded_data_size;
  unsigned char * data, * encoded_data, * dataDecoded; 
  char buf[512];
  FILE * fin, * fout;

  /* Initialization steps: check whether a file name is given */
  if(stat(argv[1], &st))
   {
    perror("stat");
    exit(0);
   }

  /* If exists, open the file                                 */
  fin = fopen(argv[1], "r");
  if((fin = fopen(argv[1], "r")) == NULL)
   {
    perror("File opening on error!");
    exit(0);
   }
 
  /* Get the file size and allocate the array                 */
  data_size = (unsigned long int)(st.st_size);
  printf("Size according to stat %lu\n", data_size);
  data = (unsigned char *)calloc(data_size, sizeof(unsigned char));

  /* Read data from file                                      */
  data_size--;
  for(i = 0L;i < data_size;i++) data[i] = (unsigned char)(getc(fin));
  fclose(fin);

#ifdef DEBUG
  printf("Data to protect = %s\n", data);
#endif
    
  /************************************************************/
  /* Generate the secret elements:                            */
  /*   - a PCC encoder                                        */
  /*   - the Noise generator secret key                       */
  /* Whenever the transmission is reset we need to generate   */
  /* these elements and send them through an https session    */
  /* before coding/decoding (https part not played here)      */
  /************************************************************/

  /* Generate the PCC encoder                                 */
  Pcc = generateCode();
  if(!Pcc)
   {
    perror("Encoder variable allocation on error!");
    free(Pcc);
    exit(0);
   }

#ifdef DEBUG
  Punct_Conc_Code_debug(Pcc, NULL);
#endif

  /* Noise generator secret key generation                    */
  aKey = generateKey();
  if(!aKey) {
    perror("Noise generator secret key variable allocation on error!");
    exit(0);
  }

#ifdef DEBUG
  Init_Noise_Gen_debug(aKey, NULL);
#endif

  /* Noise generator variable allocation                      */
  NGen = (NOISE_GEN *)calloc(1, sizeof(NOISE_GEN));
  if(!NGen)
   {
    perror("Noise generator variable allocation on error!");
    exit(0);
   }
  
  /* Noise generator init                                     */
  if(!Gen_Noise_Generator(NGen, aKey))
   {
    perror("Noise encoder generation on error!");
    free(NGen);
    exit(0);
   }
  /************************************************************/
  /* End of secret elements generation                        */
  /************************************************************/

  /***********************************************************/
  /* Http session to share the secret elements               */
  /* (not played here)                                       */
  /***********************************************************/
 
  /************************************************************/
  /* Now let us proceed with the PCC encoding. It includes:   */
  /*  - char2bin encoding                                     */
  /*  - the PCC coding itself                                 */
  /*  - data puncturing                                       */
  /*  - bin2hex encoding                                      */
  /*  - Addition of deterministic noise                       */
  /*                                                          */
  /* Message to protect is contained in the array "data"      */
  /* Final result of the PCC encoding is contained in the     */
  /* array "encoded_data"                                     */
  /************************************************************/
  encoded_data_size = 0L;
  if(!pcc_code(Pcc, data, data_size, &encoded_data, &encoded_data_size, NGen, aKey))
   {
    perror("Encoding error\n");
    exit(0);
   }

  printf("Data after PCC encoding = %s\n", encoded_data);

  /***********************************************************/
  /* Encoded data (array encoded_data) of encoded_data_size  */
  /* bytes are then sent according any protocol you choose   */
  /***********************************************************/

  /***********************************************************/
  /* Received data must now be decoded. Let us proceed with  */
  /* the PCC decoding. It includes:                          */
  /*  - Remove the deterministic noise                       */
  /*  - hex2bin encoding                                     */
  /*  - data unpuncturing                                    */
  /*  - Viterbi decoding                                     */
  /*                                                         */
  /* Encoded data are in the array "dataCoded". Decoded data */
  /* are contained in the array "dataDecoded"                */
  /***********************************************************/
  dataLength = 0L;
  if(!pcc_decode(Pcc, NGen, aKey, encoded_data, encoded_data_size, &dataDecoded, &dataLength))
   {

    perror("Decoding error\n");
    exit(1);
   }

  /* Write decoded data in a file */
  strncpy(buf, argv[1], 500);
  strncat(buf, ".decoded", 8);
  fout = fopen(buf, "w");
  if(fout == NULL)
   {
    perror("Error on opening output file\n");
    exit(0);
   }
  fprintf(fout, "%s\n", dataDecoded);
  return(0);
 }
